home *** CD-ROM | disk | FTP | other *** search
- /* setopts.c (c) copyright 1986 (Dan Heller) */
-
- #include "mush.h"
- #include "bindings.h"
-
- static void
- insert_option(list, opt, order)
- struct options **list, *opt;
- int order; /* Insert in sorted order? */
- {
- while (*list && (!order || (strcmp((*list)->option, opt->option) < 1)))
- list = &((*list)->next);
- opt->next = *list;
- *list = opt;
- }
-
- /* add an option indicated by "set option[=value]" or by "alias name alias"
- * function is recursive, so multilists get appended accordingly
- */
- add_option(list, argv)
- register struct options **list;
- register char **argv;
- {
- register struct options *tmp;
- register char *option, *value = NULL;
-
- if (!(option = *argv))
- return 1;
- /* check for one of three forms:
- * option=value option= value option = value
- */
- if (value = index(option, '=')) {
- if (value == option) {
- print("No variable specified\n");
- return 0;
- }
- /* "option=value" strip into option="option" value="value" */
- *value++ = 0; /* option is now a null terminated `option' */
- if (*value || (value = *++argv)) { /* "option= value" */
- ++argv;
- }
- } else if (*++argv && !strcmp(*argv, "=")) {
- if (value = *++argv) /* "option = value" */
- ++argv;
- }
-
- /* check for internal vars that can't be set this way */
- if (*list == set_options && check_internal(option)) {
- print("You can't change %s with \"set\".\n", option);
- return 0;
- }
-
- /* check to see if option is already set by attempting to unset it */
- if (un_set(list, option) == -1)
- return 0;
-
- /* now make a new option struct and set fields */
- if (!(tmp = (struct options *)calloc((unsigned)1,sizeof(struct options)))) {
- error("calloc");
- return -1;
- }
- tmp->option = savestr(option);
- tmp->value = savestr(value); /* strdup handles the NULL case */
-
- insert_option(list, tmp, (list != &own_hdrs));
-
- /* check for options which must have values or are used frequently */
- if (*list == set_options) {
- #if defined(CURSES) || defined(SUNTOOL)
- if (!strcmp(tmp->option, "no_reverse"))
- turnoff(glob_flags, REV_VIDEO);
- else
- #endif /* CURSES || SUNTOOL */
- #ifdef SUNTOOL
- if (!strcmp(tmp->option, "tool_help"))
- if (tmp->value && *(tmp->value))
- strdup(tool_help, tmp->value);
- else {
- int n = 0;
- char *p = getpath(TOOL_HELP, &n);
- if (n)
- strdup(tool_help, "tool_help");
- else
- strdup(tool_help, p);
- strdup(tmp->value, tool_help);
- }
- else
- #endif /* SUNTOOL */
- if (!strcmp(tmp->option, "cmd_help"))
- if (tmp->value && *(tmp->value))
- strdup(cmd_help, tmp->value);
- else {
- int n = 0; /* don't ignore no such file or directory */
- char *p = getpath(COMMAND_HELP, &n);
- if (n)
- strdup(cmd_help, "cmd_help");
- else
- strdup(cmd_help, p);
- strdup(tmp->value, cmd_help);
- }
- else if (!strcmp(tmp->option, "prompt"))
- prompt = (tmp->value)? tmp->value : DEF_PROMPT;
- else if (!strcmp(tmp->option, "warning"))
- turnon(glob_flags, WARNING);
- else if (!strcmp(tmp->option, "mil_time"))
- turnon(glob_flags, MIL_TIME);
- #ifndef MSG_SEPARATOR
- else if (!strcmp(tmp->option, "date_received"))
- turnon(glob_flags, DATE_RECV);
- #endif /* MSG_SEPARATOR */
- else if (!strcmp(tmp->option, "escape"))
- escape = (tmp->value)? tmp->value : DEF_ESCAPE;
- else if (!strcmp(tmp->option, "hdr_format"))
- hdr_format = (tmp->value)? tmp->value : DEF_HDR_FMT;
- else if (!strcmp(tmp->option, "crt")) {
- if (!istool)
- crt = (tmp->value)? max(atoi(tmp->value), 2): 18;
- }
- else if (!strcmp(tmp->option, "screen")) {
- screen = (tmp->value)? max(atoi(tmp->value), 1): 18;
- #ifdef CURSES
- if (iscurses && screen > LINES-2)
- screen = LINES-2;
- #endif /* CURSES */
- } else if (!strcmp(tmp->option, "wrapcolumn")) {
- char wval[16];
- wrapcolumn =
- (tmp->value && *(tmp->value))? max(atoi(tmp->value), 0): 78;
- #ifdef CURSES
- /* Use COLS-2 because of silly terminals like vt100 */
- if (iscurses && wrapcolumn > COLS - 2)
- wrapcolumn = COLS - 2;
- #endif /* CURSES */
- xfree(tmp->value);
- tmp->value = savestr(sprintf(wval, "%d", wrapcolumn));
- } else if (!strcmp(tmp->option, "history"))
- init_history((value && *value)? atoi(value) : 1);
- else if (!strcmp(tmp->option, "realname")) {
- char *new[4];
- new[1] = "NAME";
- new[2] = tmp->value;
- new[3] = NULL;
- (void) Setenv(3, new); /* new[0] is ignored */
- } else if (!strcmp(tmp->option, "known_hosts")) {
- register char *p;
- int n;
- /* in case user separated with commas */
- for (p = index(tmp->value, ','); p; p = index(p+1, ','))
- *p = ' ';
- free_vec(known_hosts);
- known_hosts = mk_argv(tmp->value, &n, FALSE);
- } else if (!strcmp(tmp->option, "hostname")) {
- register char *p;
- int n;
- /* in case user separated with commas */
- for (p = index(tmp->value, ','); p; p = index(p+1, ','))
- *p = ' ';
- free_vec(ourname);
- ourname = mk_argv(tmp->value, &n, FALSE);
- } else if (!strcmp(tmp->option, "complete")) {
- if (value && *value) {
- m_xlate(value); /* use the original, don't change tmp->value */
- complete = value[0];
- complist = value[1];
- } else {
- tmp->value = savestr("\\E\\CD");
- complete = '\033';
- complist = '\004';
- }
- }
- }
-
- if (*argv)
- return add_option(list, argv);
- return 1;
- }
-
- /*
- * If str is NULL, just print options and their values. Note that numerical
- * values are not converted to int upon return. If str is not NULL
- * return the string that matched, else return NULL;
- */
- char *
- do_set(list, str)
- register struct options *list;
- register char *str;
- {
- register struct options *opts;
-
- if (!str)
- (void) do_pager(NULL, TRUE); /* page using internal pager */
-
- for (opts = list; opts; opts = opts->next)
- if (!str) {
- (void) do_pager(opts->option, FALSE);
- if (opts->value && *opts->value) {
- (void) do_pager(" \t", FALSE);
- (void) do_pager(opts->value, FALSE);
- }
- if (do_pager("\n", FALSE) == EOF)
- break;
- } else {
- if (strcmp(str, opts->option))
- continue;
- if (opts->value)
- return opts->value;
- else
- return "";
- }
-
- if (!str)
- (void) do_pager(NULL, FALSE); /* terminate internal pager */
-
- /* if we still haven't matched, check for environment vars */
- if (str && list == set_options) {
- register int N, n;
- for (N = 0; environ[N]; N++) {
- char *p = index(environ[N], '=');
- if (p)
- *p = 0;
- n = lcase_strncmp(str, environ[N], -1);
- if (p)
- *p = '=';
- if (!n)
- return p+1;
- }
- }
- return NULL;
- }
-
- /*
- * unset the variable described by p in the list "list".
- * if the variable isn't set, then return 0, else return 1.
- */
- un_set(list, p)
- register struct options **list;
- register char *p;
- {
- register struct options *opts = *list, *tmp;
-
- if (!list || !*list || !p || !*p)
- return 0;
- if (*list == set_options) {
- #if defined(CURSES) || defined(SUNTOOL)
- if (!strcmp(p, "no_reverse"))
- turnon(glob_flags, REV_VIDEO);
- else
- #endif /* CURSES || SUNTOOL */
- if (!strcmp(p, "prompt"))
- prompt = DEF_PROMPT;
- else if (!strcmp(p, "warning"))
- turnoff(glob_flags, WARNING);
- else if (!strcmp(p, "mil_time"))
- turnoff(glob_flags, MIL_TIME);
- #ifndef MSG_SEPARATOR
- else if (!strcmp(p, "date_received"))
- turnoff(glob_flags, DATE_RECV);
- #endif /* MSG_SEPARATOR */
- else if (!strcmp(p, "escape"))
- escape = DEF_ESCAPE;
- else if (!strcmp(p, "hdr_format"))
- hdr_format = DEF_HDR_FMT;
- else if (!strcmp(p, "crt"))
- crt = 18;
- else if (!strcmp(p, "screen")) {
- screen = 18;
- #ifdef CURSES
- if (iscurses && screen > LINES-2)
- screen = LINES-2;
- #endif /* CURSES */
- } else
- #ifdef SUNTOOL
- if (!strcmp(p, "tool_help")) {
- int n = 0;
- char *p2 = getpath(TOOL_HELP, &n);
- if (n)
- strdup(tool_help, "tool_help");
- else
- strdup(tool_help, p2);
- } else
- #endif /* SUNTOOL */
- if (!strcmp(p, "cmd_help")) {
- int n = 0; /* don't ignore no such file or directory */
- char *p2 = getpath(COMMAND_HELP, &n);
- if (n)
- strdup(cmd_help, "cmd_help");
- else
- strdup(cmd_help, p2);
- } else if (!strcmp(p, "wrapcolumn"))
- wrapcolumn = 0;
- else if (!strcmp(p, "history"))
- init_history(1);
- else if (!strcmp(p, "known_hosts")) {
- free_vec(known_hosts);
- known_hosts = DUBL_NULL;
- } else if (!strcmp(p, "hostname")) {
- free_vec(ourname);
- ourname = DUBL_NULL;
- } else if (ison(glob_flags, IS_GETTING) && !strcmp(p, "edit_hdrs")) {
- wprint("You mush finish this letter first.\n");
- return -1;
- } else if (!strcmp(p, "complete"))
- complete = complist = 0;
- }
-
- if (!strcmp(p, opts->option)) {
- *list = (*list)->next;
- xfree (opts->option);
- if (opts->value)
- xfree(opts->value);
- xfree((char *)opts);
- return 1;
- }
- for ( ; opts->next; opts = opts->next)
- if (!strcmp(p, opts->next->option)) {
- tmp = opts->next;
- opts->next = opts->next->next;
- xfree (tmp->option);
- if (tmp->value)
- xfree(tmp->value);
- xfree ((char *)tmp);
- return 1;
- }
- return 0;
- }
-
- /* The functions below return 0 since they don't affect
- * messages.
- */
- set(n, argv, list)
- register int n;
- register char **argv;
- char *list;
- {
- void list_to_str();
- char firstchar = **argv;
- register char *cmd = *argv;
- register struct options **optlist;
- char buf[BUFSIZ];
-
- if (*cmd == 'u')
- cmd += 2;
- if (*++argv && !strcmp(*argv, "-?"))
- return help(0, (*cmd == 'i')? "ignore": "set", cmd_help);
-
- if (*argv && **argv == '?') {
- int incurses;
- if (!strcmp(*argv, "?all")) {
- if (incurses = iscurses) /* assign and compare to TRUE */
- clr_bot_line(), iscurses = FALSE;
- (void) do_pager(NULL, TRUE); /* start internal pager */
- for (n = 0; variable_stuff(n, NULL, buf); n++)
- if (do_pager(strcat(buf, "\n"), FALSE) == EOF)
- break;
- (void) do_pager(NULL, FALSE); /* terminate pager */
- iscurses = incurses;
- } else {
- /* May return null if variable not set. */
- (void) variable_stuff(0, (*argv)+1, buf);
- print("%s\n", buf);
- }
- return 0;
- }
-
- if (firstchar == 'u') {
- if (!*argv) {
- print("%s what?\n", cmd);
- return -1;
- } else {
- optlist = (*cmd == 'i')? &ignore_hdr : &set_options;
- do if (!strcmp(*argv, "*")) {
- while (*optlist)
- (void) un_set(optlist, (*optlist)->option);
- #ifdef SUNTOOL
- if (*cmd != 'i')
- opts_panel_item(NULL);
- #endif /* SUNTOOL */
- } else if (!un_set(optlist, *argv) &&
- do_set(set_options, "warning"))
- print("un%s: %s not set\n",
- (*cmd == 'i')? "ignore" : "set", *argv);
- #ifdef SUNTOOL
- else if (*cmd != 'i')
- opts_panel_item(*argv);
- #endif /* SUNTOOL */
- while (*++argv);
- #ifdef SUNTOOL
- if (*cmd == 'i' && istool > 1)
- update_list_textsw(&ignore_hdr);
- #endif /* SUNTOOL */
- }
- return 0;
- }
-
- if (!*argv) {
- (void) do_set((*cmd == 'i')? ignore_hdr: set_options, NULL);
- return 0;
- }
-
- /*
- * Check for input redirection. If so, set the variable to the ascii
- * value of the current msg_list.
- */
- if (ison(glob_flags, IS_PIPE)) {
- char *newargv[4];
-
- if (*cmd == 'i') {
- print("You can't pipe to the \"%s\" command.\n", cmd);
- return -1;
- }
- if (newargv[0] = index(argv[0], '='))
- *newargv[0] = 0;
- list_to_str(list, buf);
- if (!buf[0] && !do_set(set_options, argv[0])) {
- return 0;
- }
- newargv[0] = argv[0];
- newargv[1] = "=";
- newargv[2] = buf;
- newargv[3] = NULL;
- (void) add_option(&set_options, newargv);
- return 0;
- }
-
- /*
- * finally, just set the variable the user requested.
- */
- (void) add_option((*cmd == 'i')? &ignore_hdr: &set_options, argv);
- #ifdef SUNTOOL
- if (istool > 1)
- if (*cmd == 'i')
- update_list_textsw(&ignore_hdr);
- else
- opts_panel_item(argv[0]);
- #endif /* SUNTOOL */
- return 0;
- }
-
- /*
- * The alts list is a list of hostnames or pathnames where the user
- * has an account. If he doesn't specify "metoo", then when replying
- * to mail, if his address is listed, it will be removed. The syntax
- * is compatible with ucb Mail in that just hostnames can be used.
- * However, there is an added feature that mush provides which another
- * login name or path to another login can be specified by preceding the
- * path or login with a !
- * "argv" may be a file pointer to write the data into by use of save_opts()
- */
- alts(argc, argv)
- register char **argv;
- {
- char buf[BUFSIZ], *p;
-
- /* check here first because a 0 argc means to write it to a file */
- if (argc <= 1) {
- int n;
- if (!alternates)
- return 0;
- if (argc == 0)
- (void) fprintf((FILE *)argv, "alts ");
- for (n = 0; alternates[n]; n++) {
- p = 0;
- buf[0] = 0;
- (void) strcpy(&buf[1], alternates[n]);
- if (buf[1] != '*')
- (void) reverse(&buf[1]);
- if ((p = rindex(&buf[1], '!')) && !lcase_strncmp(p+1, login, -1))
- *p = 0;
- else if (buf[1] != '*')
- buf[0] = '!';
- if (argc == 0)
- (void) fprintf((FILE *)argv, "%s ", *buf? buf : &buf[1]);
- else
- wprint("%s ", *buf? buf : &buf[1]);
- if (p)
- *p = '!';
- }
- if (argc == 0)
- (void) fputc('\n', (FILE *)argv);
- else
- wprint("\n");
- return 0;
- }
-
- if (argc-- && *++argv && !strcmp(*argv, "-?"))
- return help(0, "alts", cmd_help);
-
- free_vec(alternates);
- if (alternates = (char **)calloc((unsigned)argc+1, sizeof(char *)))
- while (argc-- > 0) {
- if (argv[argc][0] == '!')
- alternates[argc] = savestr(reverse(&argv[argc][1]));
- else if (argv[argc][0] == '*') {
- alternates[argc] = savestr(argv[argc]);
- } else {
- p = buf + Strcpy(buf, argv[argc]);
- *p++ = '!', p += Strcpy(p, login);
- alternates[argc] = savestr(reverse(buf));
- }
- }
- return 0;
- }
-
- save_opts(cnt, argv)
- char **argv;
- {
- char file[MAXPATHLEN], *tmp;
- register FILE *fp;
-
- if (cnt && *++argv && !strcmp(*argv, "-?"))
- return help(0, "source", cmd_help);
- if (cnt && *argv)
- (void) strcpy(file, *argv);
- else if ((tmp = getenv("MUSHRC")) || (tmp = getenv("MAILRC")))
- (void) strcpy(file, tmp);
- else {
- char *home = do_set(set_options, "home");
- if (!home || !*home)
- home = ALTERNATE_HOME;
- /* if .mushrc doesn't exist, check .mailrc. If neither, force .mushrc */
- if (Access(sprintf(file, "%s/%s", home, MAILRC), F_OK) &&
- Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), F_OK))
- (void) sprintf(file, "%s/%s", home, MAILRC);
- }
-
- cnt = 1;
- tmp = getpath(file, &cnt);
- if (cnt) {
- if (cnt == -1) {
- print("%s: %s\n", file, tmp);
- return -1;
- } else {
- print("%s is a directory.\n", tmp);
- return -2;
- }
- }
- /* See if the file exists and confirm overwrite */
- if (!Access(tmp, F_OK)) {
- int overwrite = TRUE;
- char buf[BUFSIZ];
- if (!istool) {
- print("\"%s\" exists. Overwrite? ", trim_filename(tmp));
- if (Getstr(buf, 3, 0) <= 0 || lower(*buf) != 'y')
- overwrite = FALSE;
- }
- #ifdef SUNTOOL
- else {
- sprintf(buf, "\"%s\" exists. Overwrite? ", trim_filename(tmp));
- overwrite = ask(buf);
- }
- #endif /* SUNTOOL */
- if (!overwrite) {
- print("\"%s\" unchanged.\n", tmp);
- return -3;
- }
- }
- if (!(fp = fopen(tmp, "w"))) {
- error("Can't open %s", file);
- return -1;
- }
-
- save_list("basic variable settings", set_options, "set", '=', fp);
-
- save_list("mail headers for outgoing mail", own_hdrs, "my_hdr", 0, fp);
-
- save_list("aliases", aliases, "alias", 0, fp);
-
- (void) alts(0, (char **)fp);
-
- save_list("headers to ignore", ignore_hdr, "ignore", ' ', fp);
-
- save_list("command abbreviations", functions, "cmd", ' ', fp);
-
- save_list("command macros for function keys", fkeys, "fkey", ' ', fp);
-
- #ifdef CURSES
- save_cmd("curses mode key bindings", cmd_map, "bind", 1, fp);
- #endif /* CURSES */
-
- save_cmd("line mode mappings", line_map, "map", 0, fp);
-
- save_cmd("composition mode mappings", bang_map, "map!", 0, fp);
-
- (void) fclose(fp);
- print("All variables and options saved in %s\n", trim_filename(tmp));
- return 0;
- }
-
- save_list(title, list, command, equals, fp)
- struct options *list;
- register char *command, *title, equals;
- register FILE *fp;
- {
- register struct options *opts;
- register char *p;
-
- if (!list)
- return;
- (void) fprintf(fp, "#\n# %s\n#\n", title);
- for (opts = list; opts; opts = opts->next) {
- if (list == set_options && !strcmp(opts->option, "cwd"))
- continue; /* don't print $cwd */
- (void) fprintf(fp, "%s %s", command, opts->option);
- if (opts->value && *opts->value) {
- register char *quote;
- if (!equals)
- quote = NO_STRING;
- else if (p = any(opts->value, "\"'"))
- if (*p == '\'')
- quote = "\"";
- else
- quote = "'";
- else
- if (!any(opts->value, " \t;|"))
- quote = NO_STRING;
- else
- quote = "'";
- (void) fputc(equals? equals: ' ', fp);
- (void) fprintf(fp, "%s%s%s", quote, opts->value, quote);
- }
- (void) fputc('\n', fp);
- }
- }
-
- extern struct cmd_map map_func_names[];
-
- save_cmd(title, list, command, equals, fp)
- struct cmd_map *list;
- register char *command, *title;
- register int equals;
- register FILE *fp;
- {
- register struct cmd_map *opts;
- register char *p;
- char buf[MAX_MACRO_LEN * 2];
-
- if (!list)
- return;
- (void) fprintf(fp, "#\n# %s\n#\n", title);
- for (opts = list; opts; opts = opts->m_next) {
- register char *quote;
- if ((p = any(opts->m_str, "\"'")) && *p == '\'')
- quote = "\"";
- else
- quote = "'";
- (void) fprintf(fp, "%s %s%s%s", command, quote,
- ctrl_strcpy(buf, opts->m_str, TRUE), quote);
- if (equals && map_func_names[opts->m_cmd].m_str)
- (void) fprintf(fp, " %s", map_func_names[opts->m_cmd].m_str);
- if (opts->x_str && *opts->x_str) {
- if ((p = any(opts->x_str, "\"'")) && *p == '\'')
- quote = "\"";
- else
- quote = "'";
- (void) fprintf(fp, " %s%s%s", quote,
- ctrl_strcpy(buf, opts->x_str, TRUE), quote);
- }
- (void) fputc('\n', fp);
- }
- }
-
- /*
- * do_alias handles aliases, header settings, functions, and fkeys.
- * since they're all handled in the same manner, the same routine is
- * used. argv[0] determines which to use.
- * alias is given here as an example
- *
- * alias identify all aliases
- * alias name identify alias
- * alias name arg1 arg2 arg3... -> name="arg1 arg2 arg3"; call add_option
- * unalias arg1 [arg2 arg3 ... ] unalias args
- *
- * same is true for dealing with your own headers.
- * (also the expand command)
- */
- do_alias(argc, argv)
- register char **argv;
- {
- register char *cmd = *argv, *p;
- struct options **list;
- char firstchar = *cmd, buf[BUFSIZ];
-
- if (argc == 0)
- return 0 - in_pipe();
- if (firstchar == 'u')
- firstchar = cmd[2];
- if (*++argv && !strcmp(*argv, "-?")) { /* doesn't apply for fkeys */
- register char *help_str;
- if (firstchar == 'a' || firstchar == 'e')
- help_str = "alias";
- else if (firstchar == 'c')
- help_str = "cmd";
- else if (firstchar == 'f')
- help_str = "fkey";
- else
- help_str = "my_hdr";
- return help(0, help_str, cmd_help);
- }
-
- if (firstchar == 'a')
- list = &aliases;
- else if (firstchar == 'c')
- list = &functions;
- else if (firstchar == 'f')
- list = &fkeys;
- else
- list = &own_hdrs;
-
- if (*cmd == 'u') {
- if (!*argv) {
- print("%s what?\n", cmd);
- return -1;
- /* unset a list separated by spaces or ',' */
- } else while (*argv) {
- if (!strcmp(*argv, "*")) /* unset everything */
- while (*list)
- (void) un_set(list, (*list)->option);
- else if (!un_set(list, *argv))
- print("\"%s\" isn't set\n", *argv);
- argv++;
- }
- #ifdef SUNTOOL
- if (istool > 1)
- update_list_textsw(list);
- #endif /* SUNTOOL */
- return 0;
- }
-
- if (!*argv && *cmd != 'e') {
- /* just type out all the aliases or own_hdrs */
- (void) do_set(*list, NULL);
- return 0;
- }
-
- if (*cmd == 'e') { /* command was "expand" (aliases only) */
- if (!*argv) {
- print("expand which alias?\n");
- return -1;
- } else
- do {
- print("%s: ", *argv);
- if (p = alias_to_address(*argv))
- print("%s\n", p);
- } while (*++argv);
- return 0;
- }
-
- /* at this point, *argv now points to a variable name ...
- * check for hdr -- if so, *argv better end with a ':' (check *p)
- */
- if (list == &own_hdrs && !(p = index(*argv, ':'))) {
- print("header labels must end with a ':' (%s)\n", *argv);
- return -1;
- }
- if (!argv[1] && !index(*argv, '='))
- if (p = do_set(*list, *argv))
- print("%s\n", p);
- else
- print("%s is not set\n", *argv);
- else {
- char *tmpargv[2];
- (void) argv_to_string(buf, argv);
- if ((p = any(buf, " \t=")) && *p != '=')
- *p = '=';
- /* if we're setting an alias, enforce the insertion of commas
- * between each well-formed address.
- */
- if (list == &aliases)
- fix_up_addr(p+1);
- tmpargv[0] = buf;
- tmpargv[1] = NULL;
- (void) add_option(list, tmpargv);
- #ifdef SUNTOOL
- if (istool > 1)
- update_list_textsw(list);
- #endif /* SUNTOOL */
- }
- return 0;
- }
-